#pragma once

#include <cstdint>
#include <limits>
#include <sstream>
#include <array>

#include "common/macros.h"

namespace Common {
  /// 在整个系统中使用的常量，表示各种容器的上限
  /// 交易品种/股票代码范围为 [0, ME_MAX_TICKERS]
  /// 最大支持的交易品种数量
  constexpr size_t ME_MAX_TICKERS = 8;

  /// 用于在组件之间传输客户端请求、客户端响应和市场更新的无锁队列的最大大小
  constexpr size_t ME_MAX_CLIENT_UPDATES = 256 * 1024; // 客户端更新队列大小（256K）
  constexpr size_t ME_MAX_MARKET_UPDATES = 256 * 1024; // 市场数据更新队列大小（256K）

  /// 最大交易客户端数量
  constexpr size_t ME_MAX_NUM_CLIENTS = 256;

  /// 每个交易客户端的最大订单数量
  constexpr size_t ME_MAX_ORDER_IDS = 1024 * 1024; // 1M订单

  /// 订单簿中的最大价格深度
  constexpr size_t ME_MAX_PRICE_LEVELS = 256;

  /// 订单ID类型定义（64位无符号整数）
  typedef uint64_t OrderId;
  /// 无效订单ID的常量值（最大的uint64_t值）
  constexpr auto OrderId_INVALID = std::numeric_limits<OrderId>::max();

  /// 将订单ID转换为字符串表示
  inline auto orderIdToString(OrderId order_id) -> std::string {
    if (UNLIKELY(order_id == OrderId_INVALID)) { // 如果是无效订单ID
      return "INVALID";
    }

    return std::to_string(order_id);
  }

  /// 交易品种ID类型定义（32位无符号整数）
  typedef uint32_t TickerId;
  /// 无效交易品种ID的常量值
  constexpr auto TickerId_INVALID = std::numeric_limits<TickerId>::max();

  /// 将交易品种ID转换为字符串表示
  inline auto tickerIdToString(TickerId ticker_id) -> std::string {
    if (UNLIKELY(ticker_id == TickerId_INVALID)) { // 如果是无效交易品种ID
      return "INVALID";
    }

    return std::to_string(ticker_id);
  }

  /// 客户端ID类型定义（32位无符号整数）
  typedef uint32_t ClientId;
  /// 无效客户端ID的常量值
  constexpr auto ClientId_INVALID = std::numeric_limits<ClientId>::max();

  /// 将客户端ID转换为字符串表示
  inline auto clientIdToString(ClientId client_id) -> std::string {
    if (UNLIKELY(client_id == ClientId_INVALID)) { // 如果是无效客户端ID
      return "INVALID";
    }

    return std::to_string(client_id);
  }

  /// 价格类型定义（64位有符号整数，可以表示负价格）
  typedef int64_t Price;
  /// 无效价格的常量值
  constexpr auto Price_INVALID = std::numeric_limits<Price>::max();

  /// 将价格转换为字符串表示
  inline auto priceToString(Price price) -> std::string {
    if (UNLIKELY(price == Price_INVALID)) { // 如果是无效价格
      return "INVALID";
    }

    return std::to_string(price);
  }

  /// 数量类型定义（32位无符号整数）
  typedef uint32_t Qty;
  /// 无效数量的常量值
  constexpr auto Qty_INVALID = std::numeric_limits<Qty>::max();

  /// 将数量转换为字符串表示
  inline auto qtyToString(Qty qty) -> std::string {
    if (UNLIKELY(qty == Qty_INVALID)) { // 如果是无效数量
      return "INVALID";
    }

    return std::to_string(qty);
  }

  /// 优先级表示在FIFO队列中的位置，用于所有具有相同方向和价格属性的订单
  /// 优先级类型定义（64位无符号整数）
  typedef uint64_t Priority;
  /// 无效优先级的常量值
  constexpr auto Priority_INVALID = std::numeric_limits<Priority>::max();

  /// 将优先级转换为字符串表示
  inline auto priorityToString(Priority priority) -> std::string {
    if (UNLIKELY(priority == Priority_INVALID)) { // 如果是无效优先级
      return "INVALID";
    }

    return std::to_string(priority);
  }

  /// 交易方向枚举类型
  enum class Side : int8_t {
    INVALID = 0,   // 无效方向
    BUY = 1,       // 买入方向（值为1）
    SELL = -1,     // 卖出方向（值为-1）
    MAX = 2        // 用于数组索引的最大值
  };

  /// 将交易方向转换为字符串表示
  inline auto sideToString(Side side) -> std::string {
    switch (side) {
      case Side::BUY:
        return "BUY";
      case Side::SELL:
        return "SELL";
      case Side::INVALID:
        return "INVALID";
      case Side::MAX:
        return "MAX";
    }

    return "UNKNOWN"; // 未知方向
  }

  /// 将交易方向转换为可用于std::array索引的索引值
  /// 由于SELL=-1，需要+1转换为非负索引
  inline constexpr auto sideToIndex(Side side) noexcept {
    return static_cast<size_t>(side) + 1; // SELL->0, INVALID->1, BUY->2
  }

  /// 将交易方向转换为整数值：BUY=1, SELL=-1
  inline constexpr auto sideToValue(Side side) noexcept {
    return static_cast<int>(side);
  }

  /// 交易算法类型枚举
  enum class AlgoType : int8_t {
    INVALID = 0,   // 无效算法
    RANDOM = 1,    // 随机交易算法
    MAKER = 2,     // 做市商算法（提供流动性）
    TAKER = 3,     // 流动性提供者算法（吃单）
    MAX = 4        // 用于循环的最大值
  };

  /// 将算法类型转换为字符串表示
  inline auto algoTypeToString(AlgoType type) -> std::string {
    switch (type) {
      case AlgoType::RANDOM:
        return "RANDOM";
      case AlgoType::MAKER:
        return "MAKER";
      case AlgoType::TAKER:
        return "TAKER";
      case AlgoType::INVALID:
        return "INVALID";
      case AlgoType::MAX:
        return "MAX";
    }

    return "UNKNOWN"; // 未知算法类型
  }

  /// 将字符串转换为算法类型
  /// 用于从命令行参数解析算法类型
  inline auto stringToAlgoType(const std::string &str) -> AlgoType {
    // 遍历所有可能的算法类型
    for (auto i = static_cast<int>(AlgoType::INVALID); i <= static_cast<int>(AlgoType::MAX); ++i) {
      const auto algo_type = static_cast<AlgoType>(i);
      // 如果字符串匹配算法类型的字符串表示，则返回该算法类型
      if (algoTypeToString(algo_type) == str)
        return algo_type;
    }

    // 如果没有匹配的算法类型，返回无效类型
    return AlgoType::INVALID;
  }

  /// 风险配置，包含RiskManager的风险参数限制
  struct RiskCfg {
    Qty max_order_size_ = 0;  // 最大订单大小限制
    Qty max_position_ = 0;    // 最大持仓限制
    double max_loss_ = 0;     // 最大亏损限制

    /// 将风险配置转换为字符串表示，用于日志和调试
    auto toString() const {
      std::stringstream ss;

      ss << "RiskCfg{"
         << "max-order-size:" << qtyToString(max_order_size_) << " "
         << "max-position:" << qtyToString(max_position_) << " "
         << "max-loss:" << max_loss_
         << "}";

      return ss.str();
    }
  };

  /// 顶层配置，用于配置TradeEngine、交易算法和RiskManager
  struct TradeEngineCfg {
    Qty clip_ = 0;          // 单次交易的标准数量
    double threshold_ = 0;  // 交易触发阈值
    RiskCfg risk_cfg_;      // 风险配置

    /// 将交易引擎配置转换为字符串表示，用于日志和调试
    auto toString() const {
      std::stringstream ss;
      ss << "TradeEngineCfg{"
         << "clip:" << qtyToString(clip_) << " "
         << "thresh:" << threshold_ << " "
         << "risk:" << risk_cfg_.toString()
         << "}";

      return ss.str();
    }
  };

  /// 从TickerId到TradeEngineCfg的映射
  /// 使用固定大小数组实现，索引即为TickerId
  typedef std::array<TradeEngineCfg, ME_MAX_TICKERS> TradeEngineCfgHashMap;
}
